package com.ruoyi.zsix.service.impl;

import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ZSixSecurityUtiles;
import com.ruoyi.zsix.domain.model.SendActionDto;
import com.ruoyi.zsix.domain.model.TaskManageParams;
import com.ruoyi.zsix.domain.model.TaskParams;
import com.ruoyi.zsix.domain.process.ProcessTask;
import com.ruoyi.zsix.domain.taskAssignee.*;
import com.ruoyi.zsix.mapper.taskAssigneeMapper.*;
import com.ruoyi.zsix.service.IProcessTaskService;
import com.ruoyi.zsix.service.manager.CommManager;
import com.ruoyi.zsix.service.manager.IProcessTaskServiceManager;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.UUID;

@Service
public class IProcessTaskServiceImpl implements IProcessTaskService {
    @Autowired
    private OvProcessInstanceMapper ovProcessInstanceMapper;
    @Autowired //退回信息
    private ReturnWorkMapper returnWorkMapper;
    @Autowired //退回设置
    private ReturnWayMapper returnWayMapper;
    @Autowired
    private FlowElementAttrsMapper flowElementAttrsMapper;
    @Autowired
    private OvTaskEntityMapper ovTaskEntityMapper;
    @Autowired //流程发布信息服务
    private RepositoryService repositoryService;
    @Autowired
    private GenerWorkMapper generWorkMapper;
    @Autowired
    private IProcessTaskServiceManager processTaskServiceManager;
    @Autowired //流程实例服务
    private ProcessRuntime processRuntime;
    @Autowired //任务服务
    private TaskService taskService;
    @Autowired
    private CommManager commManager;
    @Autowired //历史任务服务
    private HistoryService historyService;
    @Autowired //流程运行实例服务
    private RuntimeService runtimeService;
    @Autowired //任务执行服务
    private TaskRuntime taskRuntime;

    /**
     * 获取绑定的表单
     * @param generWork
     * @return
     */
    @Override
    public HashMap<String, Object> getHisFormJson(GenerWork generWork){
        HashMap<String, Object> hashMap=new HashMap<>();
        try{
            //没有taskid说明是开始节点
            if(StringUtils.isEmpty(generWork.getTaskid())){
                //获取流程模版信息
                OvProcessInstance ovProcessInstance=ovProcessInstanceMapper.getProcessInsLastVersion(generWork.getProcesskey());
                BpmnModel bpmnModel = repositoryService.getBpmnModel(ovProcessInstance.getId_());
                //获取流程信息
                Process process=bpmnModel.getProcesses().get(0);
                StartEvent startEvent=(StartEvent)process.getInitialFlowElement();
                List<SequenceFlow> outgoingFlows = startEvent.getOutgoingFlows();
                //获取UserTask类型数据
                UserTask userTask = (UserTask) outgoingFlows.get(0).getTargetFlowElement();
                FlowElementAttrs flowElementAttrs=flowElementAttrsMapper.getFlowElementAttrs(userTask.getId());

                hashMap.put("mapJson",flowElementAttrs.getForm_url());
                hashMap.put("form_type",flowElementAttrs.getForm_type());
                hashMap.put("form_url",flowElementAttrs.getForm_url());
            }
            else{
                //获取任务信息
                OvTaskEntity task = ovTaskEntityMapper.ovTaskEntity(generWork.getTaskid());
                FlowElementAttrs flowElementAttrs=flowElementAttrsMapper.getFlowElementAttrs(task.getTask_def_key_());

                hashMap.put("mapJson",flowElementAttrs.getForm_url());
                hashMap.put("form_type",flowElementAttrs.getForm_type());
                hashMap.put("form_url",flowElementAttrs.getForm_url());
            }
            return hashMap;
        }
        catch (Exception ex){
            return hashMap;
        }
    }
    /**
     * 获取审核按钮
     * @param taskid
     * @return
     */
    @Override
    public FlowElementAttrs getElementButton(String taskid){
        OvTaskEntity task= ovTaskEntityMapper.ovTaskEntity(taskid);
        return flowElementAttrsMapper.getFlowElementAttrs(task.getTask_def_key_());
    }
    /**
     * 获取流程待办
     * @param flowName
     * @return
     */
    @Override
    public List<GenerWork> getTodoList(String flowName){
        //获取当前登录用户信息
        List<GenerWork> generWorkList=generWorkMapper.getTodoList(SecurityUtils.getUsername(),flowName);
        return generWorkList;
    }
    /**
     * 获取已办列表
     * @param
     * @return
     */
    @Override
    public List<GenerWork> getHistoricTaskInstance(String flowName){
        List<GenerWork> generWorkList=generWorkMapper.getDoneList(SecurityUtils.getUsername(),flowName);
        return generWorkList;
    }
    /**
     * 流程启动
     * @param processTask
     * @return
     */
    @Override
    public SendActionDto startProcess(ProcessTask processTask){
        //获取当前登录用户信息
        String username=SecurityUtils.getUsername();
        //securityUtil.logInAs(username);

        SendActionDto sendActionDto=new SendActionDto();
        //关联表单业务的主键，可通过参数传递过来，也可以自动生成
        String BusinessKey=processTask.getBusinessKey();
        //启动之前，进行判断
        OvProcessInstance ovProcessInstance=ovProcessInstanceMapper.getProcessInsLastVersion(processTask.getProcessKey());
        BpmnModel bpmnModel = repositoryService.getBpmnModel(ovProcessInstance.getId_());
        //获取流程信息
        Process process=bpmnModel.getProcesses().get(0);
        StartEvent startEvent=(StartEvent)process.getInitialFlowElement();
        List<SequenceFlow> outgoingFlows = startEvent.getOutgoingFlows();
        if(outgoingFlows.size()>1){
            sendActionDto.setState(400);
            sendActionDto.setMsg("发起流程失败,启动事件后面，只能有一个任务节点");
            return sendActionDto;
        }
        //获取用户任务
        UserTask userTask = (UserTask) outgoingFlows.get(0).getTargetFlowElement();
        //启动实例
        ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder
                .start()
                .withProcessDefinitionKey(processTask.getProcessKey())
                .withName(processTask.getProcessName())
                .withVariable(userTask.getId()+"_byStarter",username)
                .withBusinessKey(BusinessKey)
                .build());

        //获取任务信息
        org.activiti.engine.task.Task task = taskService.createTaskQuery()
                .processInstanceId(processInstance.getId())
                .taskCandidateOrAssigned(username)
                .singleResult();

        if(processTask.getVariables()==null){
            HashMap<String,Object> variables=new HashMap<>();
            variables.put(userTask.getId()+"_byStarter",username);
            processTask.setVariables(variables);
        }

        processTask.setTaskId(task.getId());
        processTask.setProcessInstanceId(processInstance.getId());
        return this.sendWork(processTask);
    }
    /**
     发送到下一步
     */
    @Override
    public SendActionDto sendWork(ProcessTask processTask){
        //获取当前登录用户信息
        String username= commManager.InitSecurityContextHolder();
        return processTaskServiceManager.sendWork(processTask,username);
    }
    /**
     * 驳回
     * @param returnWork
     * @return
     */
    @Override
    public OvTaskEntity returnWork(ReturnWorkEntity returnWork){
        String re_id= UUID.randomUUID().toString();
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String username = authentication.getName();

            //查询历史数据，获取节点名称
            List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery().processInstanceId(returnWork.getProc_inst_id())
                    .taskDefinitionKey(returnWork.getReturnTo_act_id()).orderByHistoricTaskInstanceStartTime().desc().list();

            HistoricTaskInstance historicTaskInstance=historicTaskInstances.get(0);
            //获取退回节点信息
            OvTaskEntity ovTaskEntity = ovTaskEntityMapper.ovTaskEntity(returnWork.getTaskid());
            OvTaskEntity taskEntity=ovTaskEntity;
            //获取退回设置
            ReturnWayEntity returnWayEntity=returnWayMapper.getReturnWay(ovTaskEntity.getTask_def_key_());

            String task_def_key=ovTaskEntity.getTask_def_key_();
            String task_def_name=ovTaskEntity.getName_();
            //增加退回记录
            ReturnWorkEntity returnWorkEntity = new ReturnWorkEntity();
            BeanUtils.copyProperties(returnWork,returnWorkEntity);
            returnWorkEntity.setId(re_id);
            returnWorkEntity.setProc_def_id(ovTaskEntity.getProc_def_id_());
            returnWorkEntity.setProc_inst_id(ovTaskEntity.getProc_inst_id_());
            returnWorkEntity.setReturn_act_id(ovTaskEntity.getTask_def_key_());
            returnWorkEntity.setReturn_act_name(ovTaskEntity.getName_());
            returnWorkEntity.setReturnTo_act_name(historicTaskInstance.getName());
            returnWorkEntity.setReturnUser(username);
            returnWorkEntity.setReturn_time(DateTime.now().toString("yyyy-MM-dd hh:mm:ss"));

            //如果退回后，需要重新走一遍，则删除，否则，不删除
            if(returnWayEntity.getRunWay().equals("none")) {
                //删除其他分支任务
                List<OvTaskEntity> taskList = ovTaskEntityMapper.ovTaskEntityByProcessInsId(returnWork.getProc_inst_id());
                for (OvTaskEntity task : taskList) {
                    if (task.getTask_def_key_().equals(ovTaskEntity.getTask_def_key_()))
                        continue;
                    else {
                        ovTaskEntityMapper.delete(task);
                    }
                }
            }
            ovTaskEntity.setId_(returnWork.getTaskid());
            ovTaskEntity.setName_(historicTaskInstance.getName());
            ovTaskEntity.setAssignee_(historicTaskInstance.getAssignee());
            ovTaskEntity.setExecution_task_def_key_(ovTaskEntity.getTask_def_key_());
            ovTaskEntity.setTask_def_key_(returnWorkEntity.getReturnTo_act_id());

            //增加退回记录
            returnWorkMapper.createReturnDetailed(returnWorkEntity);
            //更新执行节点与执行人
            ovTaskEntityMapper.setTaskStatusToReturn(ovTaskEntity);
            //增加轨迹
            processTaskServiceManager.addTaskInstTrack(returnWork.getProc_inst_id(),taskEntity,"returnWork",returnWork.getReturn_msg());

            ProcessTask processTaskParams=new ProcessTask();
            processTaskParams.setTaskId(returnWork.getTaskid());
            processTaskParams.setProcessInstanceId(returnWork.getProc_inst_id());
            processTaskParams.setMsg(returnWork.getReturn_msg());
            processTaskServiceManager.setApprovalTrack(task_def_key,task_def_name,processTaskParams,2,"驳回");

            return ovTaskEntity;
        }
        catch (Exception ex){
            returnWorkMapper.deleteReturn(re_id);
            return new OvTaskEntity();
        }
    }
    /**
     * 移交
     * @param params
     * @return
     */
    @Override
    public OvTaskEntity transfer(TaskManageParams params){
        OvTaskEntity ovTaskEntity= processTaskServiceManager.transfer(params.getProc_inst_id(),
                params.getTaskid(),params.getMsg(),params.getToUser());
        return ovTaskEntity;
    }
    /**
     * 批量移交
     * @param param
     * @return
     */
    @Override
    public String transferBatch(TaskManageParams param){
        List<TaskParams> taskParams=param.getTaskParams();
        String msg= param.getMsg();
        String toUser= param.getToUser();
        for(TaskParams tp:taskParams){
            processTaskServiceManager.transfer(tp.getProce_inst_id(),
                    tp.getTaskid(),msg,toUser);
        }
        return "执行成功";
    }
    /**
     * 加签
     * @param param
     * @return
     */
    @Override
    public OvTaskEntity countersign(TaskManageParams param){
        try{
            OvTaskEntity task=ovTaskEntityMapper.ovTaskEntity(param.getTaskid());
            if(task.getAssignee_()==null){
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(param.getTaskid()).build());
            }

            OvTaskEntity ovTaskEntity = task;
            ovTaskEntity.setAssignee_(param.getToUser());
            ovTaskEntity.setClaim_time_(DateTime.now().toString("yyyy-MM-dd hh:mm:ss"));

            //执行加签
            taskRuntime.addCandidateUsers(TaskPayloadBuilder.addCandidateUsers().withTaskId(param.getTaskid())
                    .withCandidateUser(param.getToUser()).build());
            //更新执行人
            ovTaskEntityMapper.setTaskStatus(ovTaskEntity);
            //增加轨迹
            processTaskServiceManager.addTaskInstTrack(param.getProc_inst_id(),task,"countersign", param.getMsg());

            ProcessTask processTaskParams=new ProcessTask();
            processTaskParams.setTaskId(param.getTaskid());
            processTaskParams.setProcessInstanceId(param.getProc_inst_id());
            processTaskParams.setMsg(param.getMsg());
            processTaskServiceManager.setApprovalTrack(ovTaskEntity.getTask_def_key_(),ovTaskEntity.getName_(),processTaskParams,4,"加签");
            return ovTaskEntity;
        }catch (Exception ex){
            return new OvTaskEntity();
            //mybatis数据库回滚事物，TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
    /**
     * 不同意
     * @param params
     */
    @Override
    public OvTaskEntity refuse(TaskManageParams params){
        OvTaskEntity ovTaskEntity=ovTaskEntityMapper.ovTaskEntity(params.getTaskid());
        try{
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String username = authentication.getName();
            ovTaskEntity.setAssignee_(username);

            //增加历史记录
            processTaskServiceManager.addTaskInstTrack(params.getProc_inst_id(), ovTaskEntity,"refuse", params.getMsg());
            ovTaskEntityMapper.delete(ovTaskEntity);
            ovTaskEntityMapper.setPrcoInstReason("refuse",params.getProc_inst_id());

            //设置结束时间
            ovTaskEntityMapper.setPrcoInstStatus(DateTime.now().toString("YYYY-MM-DD hh:mm:ss"),params.getProc_inst_id());
            ProcessTask processTaskParams=new ProcessTask();
            processTaskParams.setTaskId(params.getTaskid());
            processTaskParams.setProcessInstanceId(params.getProc_inst_id());
            processTaskParams.setMsg(params.getMsg());
            processTaskServiceManager.setApprovalTrack(ovTaskEntity.getTask_def_key_(),ovTaskEntity.getName_(),processTaskParams,5,"不同意");
        }
        catch (Exception ex){
            ovTaskEntityMapper.setTaskStatus(ovTaskEntity);
        }
        return ovTaskEntity;
    }
    /**
     * 手动结束
     * @param params
     */
    @Override
    public TaskManageParams setEndTask(TaskManageParams params){
        processTaskServiceManager.setEndTask(params.getProc_inst_id(),
                params.getTaskid(), params.getMsg(), new HashMap<>());
        return params;
    }
    /**
     * 批量结束流程
     * @param params
     * @return
     */
    @Override
    public TaskManageParams setEndTaskBatch(TaskManageParams params){
        List<TaskParams> taskParams=params.getTaskParams();
        String msg= params.getMsg();
        for(TaskParams tp:taskParams){
            processTaskServiceManager.setEndTask(tp.getProce_inst_id(),
                    tp.getTaskid(),msg,new HashMap<>());
        }
        return params;
    }
    /**
     * 删除流程实例
     * @param params
     */
    @Override
    public OvTaskEntity deleteProcInst(TaskManageParams params){
        OvTaskEntity ovTaskEntity=ovTaskEntityMapper.ovTaskEntity(params.getTaskid());
        try{
            //增加历史记录
            processTaskServiceManager.addTaskInstTrack(params.getProc_inst_id(), ovTaskEntity,"deleteTask", params.getMsg());
            ovTaskEntityMapper.setPrcoInstReason("deleteTask",params.getProc_inst_id());

            //设置结束时间
            ovTaskEntityMapper.setPrcoInstStatus(DateTime.now().toString("yyyy-MM-dd hh:mm:ss"),params.getProc_inst_id());
        }
        catch (Exception ex){
            ovTaskEntityMapper.setTaskStatus(ovTaskEntity);
        }
        return ovTaskEntity;
    }
}
